package com.bby.disk.manager.upload;

import cn.hutool.core.util.ObjectUtil;
import com.bby.common.config.GlobalSettings;
import com.bby.common.exception.BBYException;
import com.bby.common.utils.StatusCode;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class OfflineThreadManager {
    public static MongoTemplate mongoTemplate;
    static Map<String, OfflineThreadTask> futureMap = new HashMap<>();
    static ThreadPoolExecutor executor = new ThreadPoolExecutor(
            GlobalSettings.CORE_POOL_SIZE,
            GlobalSettings.MAX_POOL_SIZE,
            GlobalSettings.KEEP_ALIVE_TIME,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(GlobalSettings.QUEUE_CAPACITY),
            new ThreadPoolExecutor.CallerRunsPolicy());

    public static void addThreadTask(OfflineTask task) throws BBYException {
        OfflineThreadTask thread = new OfflineThreadTask(task);
        executor.execute(thread);
        futureMap.put(task.getId(), thread);
    }

    public static void removeThreadTask(String userId, String taskId) throws BBYException {
        OfflineThreadTask thread = futureMap.get(taskId);
        if (thread==null){
            OfflineTask task = mongoTemplate.findById(taskId,OfflineTask.class);
            if (task!=null) thread = new OfflineThreadTask(task);
        }else {
            executor.remove(thread);
            thread.stopRun();
        }
        if (thread == null || ObjectUtil.notEqual(thread.task.userId, userId)) {
            throw new BBYException(StatusCode.NOT_FOUND, "您没有这个离线任务！");
        }
        futureMap.remove(taskId);
        mongoTemplate.remove(new Query(Criteria.where("_id").is(taskId)), OfflineTask.class);
    }

    public static long getFinishedSize(String userId, String taskId) throws BBYException {
        OfflineThreadTask thread = futureMap.get(taskId);
        if (thread == null) {
            OfflineTask task = mongoTemplate.findById(taskId,OfflineTask.class);
            if (task==null){
                throw new BBYException(StatusCode.NOT_FOUND, "您没有这个离线任务！");
            }else {
                return "success".equals(task.status)? task.file.getSize():0;
            }
        }
        if (ObjectUtil.notEqual(thread.task.userId, userId)){
            throw new BBYException(StatusCode.NOT_FOUND, "您没有这个离线任务！");
        }
        return thread.finishedSize;
    }

    public static void retryThreadTask(String userId, String taskId) throws BBYException {
        OfflineThreadTask thread = futureMap.get(taskId);
        if (thread == null || ObjectUtil.notEqual(thread.task.userId, userId)) {
            throw new BBYException(StatusCode.NOT_FOUND, "您没有这个离线任务！");
        }
        if (!thread.isAlive()) {
            executor.execute(thread);
        }
    }

    public static OfflineThreadTask getStatus(String taskId) {
        return futureMap.get(taskId);
    }

    public static List<OfflineTask> listOfflineTask(String userId) {
        return mongoTemplate.find(Query.query(Criteria.where("userId").is(userId)),OfflineTask.class);
    }

    public static void saveTask(OfflineTask task) {
        mongoTemplate.save(task);
    }

    public static OfflineTask getOfflineTask(String userId, String taskId) throws BBYException {
        OfflineThreadTask thread = futureMap.get(taskId);
        if (thread == null) {
            OfflineTask task = mongoTemplate.findById(taskId,OfflineTask.class);
            if (task==null){
                throw new BBYException(StatusCode.NOT_FOUND, "您没有这个离线任务！");
            }
            return task;
        }
        return thread.task;
    }

    public static void shutdown() {
        executor.shutdownNow();
    }

}
